package ltg.ibutton.aquaroom.gui.desktop;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.JFrame;

import ltg.ibutton.aquaroom.ColorBand;
import ltg.ibutton.aquaroom.HavingColor;
import ltg.ibutton.aquaroom.AquaRoomPersistence;
import ltg.ibutton.core.Concept;
import ltg.ibutton.core.FactorySimulation;
import ltg.ibutton.core.Simulation;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class SpectrometerGui extends JFrame implements Observer {
	private static final long serialVersionUID = 1L;
	
	private JFreeChart chart = null;
	private Simulation sim = null;
	
	public SpectrometerGui() {
		super();
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//this.setUndecorated(true);

        //GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        //gd.setFullScreenWindow(this);
		
		// create the chart...
		chart = ChartFactory.createXYLineChart(
		    "Spectroscopic Analysis",
		    "Wavelength (nm)",
		    "Intensity",
		    null,
		    PlotOrientation.VERTICAL,
		    false,    // legend?
		    false,    // tooltips?
		    false    // URLs?
		);		
		
		XYPlot plot = (XYPlot) chart.getPlot();
		
		// change the auto tick unit selection to integer units only...
		NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
		xAxis.setRange(380, 750);
		xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
		
		NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
		yAxis.setRange(0, 1);
		
		XYSplineRenderer renderer = new XYSplineRenderer();
		
		renderer.setSeriesPaint(0,Color.black);
		renderer.setSeriesStroke(0, new BasicStroke(2.0f));
		renderer.setSeriesLinesVisible(0, true);
		renderer.setSeriesShapesVisible(0, false);
		
		plot.setRenderer(renderer);
		plot.setBackgroundPaint(Color.white);
		plot.setDomainGridlinePaint(Color.lightGray);
		plot.setRangeGridlinePaint(Color.lightGray);
		
		ChartPanel chartPanel = new ChartPanel(
				chart, // the chart
				1024, // preferred width
				768, // preferred height
				0, // minimum drawing width
				0, // minimum drawing height
				1024, // maximum drawing width
				768, // maximum drawing height
				true, // useBuffer
				false, // properties
				false, // copy
				false, // save
				false, // print
				false, // zoom
				false // tooltips				
		);
		chartPanel.setBackground(Color.white);
		chartPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 50, 50));
		chartPanel.setDomainZoomable(false);
		chartPanel.setRangeZoomable(false);
		
		this.getContentPane().add(chartPanel);
		
		this.setSize(1024,768);
		this.setBackground(Color.white);
		this.setForeground(Color.white);
        this.setVisible(true);
        
        sim = FactorySimulation.getSim();
        sim.addObserver(this);
	}
	
	private void populateDataSet(ArrayList<ColorBand> data) {
		XYSeries series = new XYSeries("XYGraph");
		if(!data.isEmpty()) {
			Collections.sort(data);
			for(int x=350; x<750; x++) {
				double y = 0;
				for(Iterator<ColorBand> i = data.iterator(); i.hasNext();) {
					if(data.get(0) == null) { /* empty tube either because a new one or because contains a sample from a rocky area*/
						//System.err.println("tube vuota");
						y = 0.01;
						i.next();
					}
					else {
						ColorBand aux = i.next();
						if(aux.inBand(x)) {
							//System.err.println("in band " + aux.getMin() + " " + aux.getMax());
							double tmp = (1/Math.sqrt(25*Math.PI))*Math.exp(-Math.pow((x-(aux.getMin()+aux.getMax())/2),2)/25)*8.5*aux.getLvl()+0.02; 
							if(tmp > y)
								y = tmp;
						}
					}
				}
				if(y == 0)
					y = Math.sin(Math.PI*4.5*x/180)/100*Math.random()+0.02;
				//System.err.println(x + " " + y);
				series.add(x,y);
			}
		}
		else { /* sample without any dye */
			for(int x=350; x<750; x++) {
				series.add(x,Math.sin(Math.PI*4.5*x/180)/100*Math.random()+0.02);
			}
		}
		
		//Add the series to your data set
		XYSeriesCollection xydata = new XYSeriesCollection();
		xydata.addSeries(series);
		chart.getXYPlot().setDataset(xydata);
	}

	@Override
	public void update(Observable arg0, Object arg1) {
		ArrayList<String> ib = (ArrayList<String>) arg1;
		if(ib.isEmpty()) {
			chart.getXYPlot().setDataset(new XYSeriesCollection());
		}
		else {
			for(Iterator<String> i=ib.iterator(); i.hasNext();) {
				AquaRoomPersistence.writeSpectrometerLog(i.next());
			}
			ArrayList<Concept> c = sim.getSimulationState();
			ArrayList<ColorBand> bands = new ArrayList<ColorBand>();
			
			for(Iterator<Concept> i = c.iterator(); i.hasNext();) {
				HavingColor tmp = (HavingColor) i.next();				
				for(Iterator<ColorBand> j = tmp.getColors().iterator(); j.hasNext();)
					bands.add(j.next());
			}
			populateDataSet(bands);
		}
	}
}
